package com.sunlands.qdcy.deskmate.service;

import com.sunlands.qdcy.deskmate.config.WechatConfig;
import com.sunlands.qdcy.deskmate.dao.pojo.OrderRecordDO;
import com.sunlands.qdcy.deskmate.dao.pojo.PaymentWechatCloseRecord;
import com.sunlands.qdcy.deskmate.dao.pojo.PaymentWechatNoticeRecord;
import com.sunlands.qdcy.deskmate.dao.pojo.PaymentWechatRecord;
import com.sunlands.qdcy.deskmate.dao.repository.PaymentWechatCloseRecordRepository;
import com.sunlands.qdcy.deskmate.dao.repository.PaymentWechatNoticeRecordRepository;
import com.sunlands.qdcy.deskmate.dao.repository.PaymentWechatRecordRepository;
import com.sunlands.qdcy.deskmate.enums.*;
import com.sunlands.qdcy.deskmate.util.HttpClientUtil;
import com.sunlands.qdcy.deskmate.util.OrderSnUtil;
import com.sunlands.qdcy.deskmate.util.PayUtils;
import com.sunlands.qdcy.deskmate.util.RequestUtil;
import com.sunlands.qdcy.deskmate.vo.Order;
import com.sunlands.qdcy.deskmate.vo.WechatCreateOrderVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.RejectedExecutionException;

/**
 * @author zl
 * @version 1.0
 * @date Created in 2020/4/11
 */

@Slf4j
@Service
public class WechatPayService {

    @Autowired
    private WechatConfig wechatConfig;

    @Autowired
    private OrderRecordService orderRecordService;

    @Autowired
    private PaymentWechatRecordRepository paymentWechatRecordRepository;

    @Autowired
    private PaymentWechatNoticeRecordRepository wechatNoticeRecordRepository;

    @Autowired
    private PaymentWechatCloseRecordRepository wechatCloseRecordRepository;

    @Resource(name = "taskExecutor")
    private AsyncTaskExecutor taskExecutor;


    @Transactional(rollbackFor = Exception.class)
    public WechatCreateOrderVO createOrder(Order order) throws Exception {
        // 这里有风险，有可能小数点后多处很长的数字
        BigDecimal totalAmount = order.getTotalAmount().setScale(2, BigDecimal.ROUND_HALF_UP);
        order.setTotalAmount(totalAmount);
        order.setOutTradeNo(OrderSnUtil.getOrderSn(PayType.WECHAT.getType()));

        BigDecimal money = order.getTotalAmount().multiply(BigDecimal.valueOf(100));
        PaymentWechatRecord paymentWechatRecord = PaymentWechatRecord.builder().outTradeNo(order.getOutTradeNo())
                .totalAmount(order.getTotalAmount())
                .payMoney(Integer.parseInt(new DecimalFormat("#").format(money)))
                .userId(order.getUserId())
                .timeExpire(DateUtils.addHours(new Date(), 1))
                .build();

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("mch_id", wechatConfig.getMchId());
        params.put("appid", wechatConfig.getSpAppid());
        params.put("body", wechatConfig.getBody() + order.getSubject());

        String nonce_str = UUID.randomUUID().toString().trim().replaceAll("-", "");//随机字符串，不长于32位
        params.put("nonce_str", nonce_str);
        params.put("out_trade_no", order.getOutTradeNo());
        params.put("notify_url", wechatConfig.getNotifyUrl());
        params.put("total_fee", paymentWechatRecord.getPayMoney());
        params.put("spbill_create_ip", order.getSpbillIp());
        params.put("trade_type", "APP");
        params.put("time_expire", getWxDateString(paymentWechatRecord.getTimeExpire()));
        String sign = RequestUtil.getMd5ForSig(params, wechatConfig.getSecretekey(), wechatConfig.getMchMiyao());
        params.put("sign", sign);
        String pxml = PayUtils.map2Xml(params);

        log.info("微信支付下单，params={}", pxml);
        long begin = System.currentTimeMillis();
        String result = HttpClientUtil.post(wechatConfig.getTradeNoUrl(), pxml);
        log.info("微信支付下单花费{}ms,userId={},outTradeNo={},response={}", (System.currentTimeMillis() - begin), order.getUserId(), order.getOutTradeNo(), result);
        Map rmap = PayUtils.xml2map(result, false);

        paymentWechatRecord.setReturnCode(getWxFiledStrVal(rmap, "return_code"));
        paymentWechatRecord.setReturnMsg(getWxFiledStrVal(rmap, "return_msg"));

        if (!PayStatus.success.getCode().equals(getWxFiledStrVal(rmap, "return_code"))) {
            log.error("微信支付下单返回失败,userId={},outTradeNo={},returnCode={},returnMsg={}", order.getUserId(), order.getOutTradeNo(), paymentWechatRecord.getReturnCode(), paymentWechatRecord.getReturnMsg());

            paymentWechatRecordRepository.save(paymentWechatRecord);
            return null;
        }

        paymentWechatRecord.setResultCode(getWxFiledStrVal(rmap, "result_code"));
        paymentWechatRecord.setErrCode(getWxFiledStrVal(rmap, "err_code"));
        paymentWechatRecord.setReturnMsg(getWxFiledStrVal(rmap, "err_code_des"));
        paymentWechatRecord.setNonceStr(getWxFiledStrVal(rmap, "nonce_str"));

        if (!PayStatus.success.getCode().equals(getWxFiledStrVal(rmap, "result_code"))) {
            log.error("微信支付下单结果失败,userId={},outTradeNo={},resultCode={},errCode={},errCodeDes={}", order.getUserId(), order.getOutTradeNo()
                    , paymentWechatRecord.getResultCode(), paymentWechatRecord.getErrCode(), paymentWechatRecord.getErrCodeDes());
            paymentWechatRecordRepository.save(paymentWechatRecord);
            return null;
        }

        paymentWechatRecord.setTradeNo(getWxFiledStrVal(rmap, "prepay_id"));
        paymentWechatRecord.setTradeType(getWxFiledStrVal(rmap, "trade_type"));

        paymentWechatRecordRepository.save(paymentWechatRecord);

        OrderRecordDO orderRecordDO = OrderRecordDO.builder()
                .body(order.getBody())
                .outTradeNo(order.getOutTradeNo())
                .tradeNo(paymentWechatRecord.getTradeNo())
                .appId(wechatConfig.getSpAppid())
                .userId(order.getUserId())
                .goodsNumber(order.getGoodsNumber())
                .totalAmount(order.getTotalAmount())
                .orderStatus(OrderStatus.PAY_WAITING.name())
                .subject(order.getSubject())
                .body(order.getBody())
                .payType(PayType.WECHAT.name())
                .send(YN.NO.code)
                .build();

        orderRecordService.save(orderRecordDO);


        WechatCreateOrderVO orderVO = WechatCreateOrderVO.builder().appid(wechatConfig.getSpAppid())
                .noncestr(paymentWechatRecord.getNonceStr())
                .outTradeNo(paymentWechatRecord.getOutTradeNo())
                .packages(wechatConfig.getPackages())
                .partnerid(wechatConfig.getMchId())
                .payMoney(paymentWechatRecord.getPayMoney().toString())
                .prepayid(paymentWechatRecord.getTradeNo())
                .timestamp(System.currentTimeMillis() / 1000 + "")
                .tradeNo(paymentWechatRecord.getTradeNo())
                .build();

        Map<String, Object> param = new HashMap<String, Object>();
        param.put("noncestr", orderVO.getNoncestr());
        param.put("timestamp", orderVO.getTimestamp());
        param.put("appid", orderVO.getAppid());
        param.put("partnerid", orderVO.getPartnerid());
        param.put("prepayid", orderVO.getPrepayid());
        param.put("package", orderVO.getPackages());
        orderVO.setSign(RequestUtil.getMd5ForSig(param, wechatConfig.getSecretekey(), wechatConfig.getMchMiyao()));

        return orderVO;


    }

    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> payNotice(String body) {
        Map<String, Object> remap = new HashMap<>();
        try {
            Map<String, Object> bodyMap = PayUtils.xml2map(body, false);
            if (!PayStatus.success.getCode().equals(getWxFiledStrVal(bodyMap, "return_code"))) {
                log.error("微信支付回调 返回失败，return_code={},return_msg={}", getWxFiledStrVal(bodyMap, "return_code"), getWxFiledStrVal(bodyMap, "return_msg"));
                remap.put("return_code", PayStatus.failed.getCode());
                remap.put("return_msg", getWxFiledStrVal(bodyMap, "return_msg"));
                return remap;
            }

            String sign = getWxFiledStrVal(bodyMap, "sign");
            bodyMap.remove("sign");
            String signtemp = RequestUtil.getMd5ForSig(bodyMap, wechatConfig.getSecretekey(), wechatConfig.getMchMiyao()).toUpperCase();
            String outTradeNo = getWxFiledStrVal(bodyMap, "out_trade_no");
            if (!sign.equals(signtemp)) {
                log.error("微信支付回调 签名校验失败，outTradeNo={},sign={},ownSign={}", outTradeNo, sign, signtemp);
                remap.put("return_code", PayStatus.failed.getCode());
                remap.put("return_msg", "签名校验失败");
                return remap;
            }

            PaymentWechatNoticeRecord noticeRecord = PaymentWechatNoticeRecord.builder()
                    .confirmType(WechatConfirmType.notice.getCode())
                    .returnCode(getWxFiledStrVal(bodyMap, "return_code"))
                    .returnMsg(getWxFiledStrVal(bodyMap, "return_msg"))
                    .outTradeNo(outTradeNo)
                    .resultCode(getWxFiledStrVal(bodyMap, "result_code"))
                    .errCode(getWxFiledStrVal(bodyMap, "err_code"))
                    .errCodeDes(getWxFiledStrVal(bodyMap, "err_code_des"))
                    .openId(getWxFiledStrVal(bodyMap, "openid"))
                    .subscribe(getWxFiledStrVal(bodyMap, "is_subscribe"))
                    .tradeType(getWxFiledStrVal(bodyMap, "trade_type"))
                    .bankType(getWxFiledStrVal(bodyMap, "bank_type"))
                    .payMoney(getWxFiledIntVal(bodyMap, "total_fee"))
                    .feeType(getWxFiledStrVal(bodyMap, "fee_type"))
                    .cashFee(getWxFiledIntVal(bodyMap, "cash_fee"))
                    .cashFeeType(getWxFiledStrVal(bodyMap, "cash_fee_type"))
                    .transactionId(getWxFiledStrVal(bodyMap, "transaction_id"))
                    .payTimeEnd(getWxFiledDateVal(bodyMap, "time_end"))
                    .build();

            if (!PayStatus.success.getCode().equals(getWxFiledStrVal(bodyMap, "result_code"))) {
                log.error("微信支付回调 结果失败,outTradeNo={},resultCode={},errCode={},errCodeDes={}", outTradeNo
                        , noticeRecord.getResultCode(), noticeRecord.getErrCode(), noticeRecord.getErrCodeDes());
                noticeRecord = wechatNoticeRecordRepository.save(noticeRecord);

                remap.put("return_code", PayStatus.failed.getCode());
                remap.put("return_msg", noticeRecord.getErrCodeDes());
                return remap;
            }

            OrderRecordDO orderRecordDO = orderRecordService.findByOutTradeNo(outTradeNo);
            if (Objects.isNull(orderRecordDO)) {
                noticeRecord.setTradeState(WechatTradeState.own_order_absent.getCode());
                noticeRecord.setTradeStateDesc(WechatTradeState.own_order_absent.getMsg());
                noticeRecord = wechatNoticeRecordRepository.save(noticeRecord);
                log.error("微信支付回调 订单不存在,outTradeNo={}，noticeRecordId={}", outTradeNo, noticeRecord.getId());

                remap.put("return_code", PayStatus.failed.getCode());
                remap.put("return_msg", "订单号不存在：" + outTradeNo);
                return remap;
            }

            if (OrderStatus.PAY_SUCCESS.name().equals(orderRecordDO.getOrderStatus())) {
                noticeRecord.setTradeState(WechatTradeState.own_repeat_notice.getCode());
                noticeRecord.setTradeStateDesc(WechatTradeState.own_repeat_notice.getMsg());
                noticeRecord = wechatNoticeRecordRepository.save(noticeRecord);
                log.error("微信支付回调 重复，该订单已经是支付状态,outTradeNo={}，noticeRecordId={}", outTradeNo, noticeRecord.getId());
                remap.put("return_code", PayStatus.success.getCode());
                remap.put("return_msg", "OK");
                return remap;
            }

            BigDecimal money = orderRecordDO.getTotalAmount().multiply(BigDecimal.valueOf(100));
            Integer totalFee = Integer.parseInt(new DecimalFormat("#").format(money));
            if (!totalFee.equals(noticeRecord.getPayMoney())) {
                noticeRecord.setTradeState(WechatTradeState.own_payfee_unmatch.getCode());
                noticeRecord.setTradeStateDesc(WechatTradeState.own_payfee_unmatch.getMsg());
                noticeRecord = wechatNoticeRecordRepository.save(noticeRecord);
                log.error("微信支付回调 支付金额不正确,outTradeNo={}，订单金额{}，支付金额{},noticeRecordId={}", outTradeNo, totalFee, noticeRecord.getPayMoney(), noticeRecord.getId());
                remap.put("return_code", PayStatus.failed.getCode());
                remap.put("return_msg", "支付金额不正确");
                return remap;
            }

            log.info("微信支付回调 支付成功,outTradeNo={},noticeRecordId={}", outTradeNo, noticeRecord.getId());

            noticeRecord.setTradeState(WechatTradeState.SUCCESS.getCode());
            noticeRecord.setTradeStateDesc(WechatTradeState.SUCCESS.getMsg());
            noticeRecord = wechatNoticeRecordRepository.save(noticeRecord);

            orderRecordDO.setOrderStatus(OrderStatus.PAY_SUCCESS.name());
            orderRecordDO.setPaymentTime(noticeRecord.getPayTimeEnd());
            orderRecordDO.setPayEndTime(new Date());
            orderRecordService.save(orderRecordDO);

            taskExecutor.execute(() -> orderRecordService.sendGoods(outTradeNo));

            remap.put("return_code", PayStatus.success.getCode());
            remap.put("return_msg", "OK");
            return remap;

        } catch (Exception e) {
            log.error("微信支付回调 处理结果异常 ，body ={}", body, e);
            remap.put("return_code", PayStatus.failed.getCode());
            remap.put("return_msg", "处理结果失败");
            return remap;
        }

    }

    public OrderRecordDO checkOrderFromWechat(String outTradeNo) {
        OrderRecordDO orderRecordDO = orderRecordService.findByOutTradeNo(outTradeNo);
        if (Objects.isNull(orderRecordDO)) {
            log.error("核对微信订单信息，订单不存在,outTradeNo={}", outTradeNo);
            return null;
        }
        return checkOrderFromWechat(orderRecordDO);
    }

    public OrderRecordDO checkOrderFromWechat(OrderRecordDO orderRecordDO) {
        if (Objects.isNull(orderRecordDO)) {
            log.error("核对微信订单信息，订单参数为空");
            return null;
        }
        String outTradeNo = orderRecordDO.getOutTradeNo();
        if (OrderStatus.PAY_SUCCESS.name().equals(orderRecordDO.getOrderStatus())) {
            log.warn("核对微信订单信息，订单已经是支付状态,outTradeNo={}", outTradeNo);
            return orderRecordDO;
        }

        try {

            PaymentWechatNoticeRecord noticeRecord = pullOrderStatus(outTradeNo);
            noticeRecord = wechatNoticeRecordRepository.save(noticeRecord);

            if (WechatTradeState.SUCCESS.getCode().equals(noticeRecord.getTradeState())) {

                log.info("核对微信订单信息 支付成功,outTradeNo={},noticeRecordId={}", outTradeNo, noticeRecord.getId());
                orderRecordDO.setOrderStatus(OrderStatus.PAY_SUCCESS.name());
                orderRecordDO.setPaymentTime(noticeRecord.getPayTimeEnd());
                orderRecordDO.setPayEndTime(new Date());
                orderRecordService.save(orderRecordDO);

                try {
                    taskExecutor.execute(() -> orderRecordService.sendGoods(outTradeNo));
                } catch (RejectedExecutionException e) {
                    log.warn("核对微信订单信息 提交发货任务失败 ，outTradeNo={}", outTradeNo, e);
                    orderRecordService.sendGoods(outTradeNo);
                }
            } else if (WechatTradeState.CLOSED.getCode().equals(noticeRecord.getTradeState())
                    || WechatTradeState.REVOKED.getCode().equals(noticeRecord.getTradeState())
                    || WechatTradeState.PAYERROR.getCode().equals(noticeRecord.getTradeState())) {

                log.info("核对微信订单信息 订单关闭,outTradeNo={},tradeState={},noticeRecordId={}", outTradeNo, noticeRecord.getTradeState(), noticeRecord.getId());
                orderRecordDO.setOrderStatus(OrderStatus.CANCEL.name());
                orderRecordDO.setPayEndTime(new Date());
                orderRecordService.save(orderRecordDO);

            }

            log.warn("核对微信订单信息 其他状态暂不处理,outTradeNo={},tradeState={},noticeRecordId={}", outTradeNo, noticeRecord.getTradeState(), noticeRecord.getId());

            return orderRecordDO;

        } catch (Exception e) {
            log.error("核对微信订单信息异常，outTradeNo={}", outTradeNo, e);
        }

        return orderRecordDO;
    }


    public PaymentWechatNoticeRecord pullOrderStatus(String outTradeNo) throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("mch_id", wechatConfig.getMchId());
        params.put("appid", wechatConfig.getSpAppid());
        String nonce_str = UUID.randomUUID().toString().trim().replaceAll("-", "");//随机字符串，不长于32位
        params.put("nonce_str", nonce_str);
        params.put("out_trade_no", outTradeNo);
        String sign = RequestUtil.getMd5ForSig(params, wechatConfig.getSecretekey(), wechatConfig.getMchMiyao());
        params.put("sign", sign);
        String pxml = PayUtils.map2Xml(params);

        log.info("核对微信订单信息，params={}", pxml);
        long begin = System.currentTimeMillis();

        String result = HttpClientUtil.post(wechatConfig.getTradeInfoUrl(), pxml);
        log.info("核对微信订单信息花费{}ms,outTradeNo={},response={}", (System.currentTimeMillis() - begin), outTradeNo, result);

        Map<String, Object> bodyMap = PayUtils.xml2map(result, false);
        if (!PayStatus.success.getCode().equals(getWxFiledStrVal(bodyMap, "return_code"))) {
            log.error("核对微信订单信息 返回失败，return_code={},return_msg={}", getWxFiledStrVal(bodyMap, "return_code"), getWxFiledStrVal(bodyMap, "return_msg"));
            return null;
        }

        if (!PayStatus.success.getCode().equals(getWxFiledStrVal(bodyMap, "result_code"))) {
            log.error("核对微信订单信息 结果失败,outTradeNo={},resultCode={},errCode={},errCodeDes={}", outTradeNo
                    , getWxFiledStrVal(bodyMap, "result_code"), getWxFiledStrVal(bodyMap, "err_code"), getWxFiledStrVal(bodyMap, "err_code_des"));
            return null;
        }

        PaymentWechatNoticeRecord noticeRecord = PaymentWechatNoticeRecord.builder()
                .confirmType(WechatConfirmType.query.getCode())
                .returnCode(getWxFiledStrVal(bodyMap, "return_code"))
                .returnMsg(getWxFiledStrVal(bodyMap, "return_msg"))
                .outTradeNo(outTradeNo)
                .resultCode(getWxFiledStrVal(bodyMap, "result_code"))
                .errCode(getWxFiledStrVal(bodyMap, "err_code"))
                .errCodeDes(getWxFiledStrVal(bodyMap, "err_code_des"))
                .openId(getWxFiledStrVal(bodyMap, "openid"))
                .subscribe(getWxFiledStrVal(bodyMap, "is_subscribe"))
                .tradeType(getWxFiledStrVal(bodyMap, "trade_type"))
                .bankType(getWxFiledStrVal(bodyMap, "bank_type"))
                .payMoney(getWxFiledIntVal(bodyMap, "total_fee"))
                .feeType(getWxFiledStrVal(bodyMap, "fee_type"))
                .cashFee(getWxFiledIntVal(bodyMap, "cash_fee"))
                .cashFeeType(getWxFiledStrVal(bodyMap, "cash_fee_type"))
                .transactionId(getWxFiledStrVal(bodyMap, "transaction_id"))
                .payTimeEnd(getWxFiledDateVal(bodyMap, "time_end"))
                .tradeState(getWxFiledStrVal(bodyMap, "trade_state"))
                .tradeStateDesc(getWxFiledStrVal(bodyMap, "trade_state_desc"))
                .build();
        return noticeRecord;
    }


    public OrderRecordDO closeOrderFromWechat(String outTradeNo) {
        OrderRecordDO orderRecordDO = orderRecordService.findByOutTradeNo(outTradeNo);
        if (Objects.isNull(orderRecordDO)) {
            log.error("关闭微信订单，订单不存在,outTradeNo={}", outTradeNo);
            return null;
        }
        return closeOrderFromWechat(orderRecordDO);
    }

    /**
     * 先从微信核对订单状态再关闭
     *
     * @param orderRecordDO
     * @return
     */
    public OrderRecordDO closeOrderFromWechat(OrderRecordDO orderRecordDO) {
        if (Objects.isNull(orderRecordDO)) {
            log.error("关闭微信订单，订单参数为空");
            return null;
        }

        orderRecordDO = checkOrderFromWechat(orderRecordDO);
        String outTradeNo = orderRecordDO.getOutTradeNo();
        if (!OrderStatus.PAY_WAITING.name().equals(orderRecordDO.getOrderStatus())) {
            log.warn("关闭微信订单，当前订单状态不能取消,outTradeNo={},orderStatus={}", outTradeNo, orderRecordDO.getOrderStatus());
            return orderRecordDO;
        }
        if(orderRecordDO.getCreateTime().after(DateUtils.addHours(new Date(),-1))){
            log.warn("关闭微信订单，当前订单未超过1小时，先不取消,outTradeNo={},createTime={}", outTradeNo, orderRecordDO.getCreateTime());
            return orderRecordDO;
        }

        try {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("mch_id", wechatConfig.getMchId());
            params.put("appid", wechatConfig.getSpAppid());
            String nonce_str = UUID.randomUUID().toString().trim().replaceAll("-", "");//随机字符串，不长于32位
            params.put("nonce_str", nonce_str);
            params.put("out_trade_no", outTradeNo);
            String sign = RequestUtil.getMd5ForSig(params, wechatConfig.getSecretekey(), wechatConfig.getMchMiyao());
            params.put("sign", sign);
            String pxml = PayUtils.map2Xml(params);

            log.info("关闭微信订单，params={}", pxml);
            long begin = System.currentTimeMillis();
            String result = HttpClientUtil.post(wechatConfig.getCloseorderUrl(), pxml);
            log.info("关闭微信订单花费{}ms,outTradeNo={},response={}", (System.currentTimeMillis() - begin), outTradeNo, result);

            Map<String, Object> bodyMap = PayUtils.xml2map(result, false);

            if (!PayStatus.success.getCode().equals(getWxFiledStrVal(bodyMap, "return_code"))) {
                log.error("关闭微信订单 返回失败，return_code={},return_msg={}", getWxFiledStrVal(bodyMap, "return_code"), getWxFiledStrVal(bodyMap, "return_msg"));
                return orderRecordDO;
            }

            PaymentWechatCloseRecord wechatCloseRecord = PaymentWechatCloseRecord.builder()
                    .returnCode(getWxFiledStrVal(bodyMap, "return_code"))
                    .returnMsg(getWxFiledStrVal(bodyMap, "return_msg"))
                    .resultCode(getWxFiledStrVal(bodyMap, "result_code"))
                    .errCode(getWxFiledStrVal(bodyMap, "err_code"))
                    .errCodeDes(getWxFiledStrVal(bodyMap, "err_code_des"))
                    .outTradeNo(outTradeNo)
                    .build();

            wechatCloseRecordRepository.save(wechatCloseRecord);

            if (PayStatus.success.getCode().equals(getWxFiledStrVal(bodyMap, "result_code"))) {

                log.info("关闭微信订单成功,outTradeNo={}", outTradeNo);
                orderRecordDO.setOrderStatus(OrderStatus.CANCEL.name());
                orderRecordDO.setPayEndTime(new Date());
                orderRecordService.save(orderRecordDO);

                return orderRecordDO;
            }

            log.warn("关闭微信订单 结果失败,outTradeNo={},orderStatus={},resultCode={},errCode={},errCodeDes={}", outTradeNo, orderRecordDO.getOrderStatus()
                    , getWxFiledStrVal(bodyMap, "result_code"), getWxFiledStrVal(bodyMap, "err_code"), getWxFiledStrVal(bodyMap, "err_code_des"));

            if ("ORDERCLOSED".equals(wechatCloseRecord.getErrCode())) {
                log.info("关闭微信订单 订单重复关闭,outTradeNo={}", outTradeNo);
                orderRecordDO.setOrderStatus(OrderStatus.CANCEL.name());
                orderRecordDO.setPayEndTime(new Date());
                orderRecordService.save(orderRecordDO);

            } else if ("ORDERPAID".equals(wechatCloseRecord.getErrCode())) {
                log.info("关闭微信订单 订单已支付，不能发起关单,outTradeNo={}", outTradeNo);
                orderRecordDO.setOrderStatus(OrderStatus.PAY_SUCCESS.name());
                orderRecordDO.setPaymentTime(new Date());
                orderRecordDO.setPayEndTime(new Date());
                orderRecordService.save(orderRecordDO);

                try {
                    orderRecordService.sendGoods(outTradeNo);
                } catch (RejectedExecutionException e) {
                    log.warn("核对微信订单信息 提交发货任务失败 ，outTradeNo={}", outTradeNo, e);
                }

            }


            return orderRecordDO;

        } catch (Exception e) {
            log.error("关闭微信订单异常，outTradeNo={}", outTradeNo, e);
        }
        return orderRecordDO;
    }


    private String getWxDateString(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        return DateFormatUtils.format(date, "yyyyMMddHHmmss");
    }

    private Date getWxFiledDateVal(Map<String, Object> rmap, String key) {
        String object = getWxFiledStrVal(rmap, key);
        if (Objects.isNull(object)) {
            return null;
        }
        try {
            return DateUtils.parseDate(object, "yyyyMMddHHmmss");
        } catch (ParseException e) {
            log.error("微信时间转化错误，val={}", object);
        }
        return null;
    }

    private Integer getWxFiledIntVal(Map<String, Object> rmap, String key) {
        String object = getWxFiledStrVal(rmap, key);
        if (Objects.isNull(object)) {
            return null;
        }
        return Integer.valueOf(object);
    }

    private String getWxFiledStrVal(Map<String, Object> rmap, String key) {
        Object object = getWxFiledVal(rmap, key);
        if (Objects.isNull(object)) {
            return null;
        }
        return object.toString();
    }

    private Object getWxFiledVal(Map<String, Object> rmap, String key) {
        if (Objects.isNull(rmap)) {
            return null;
        }
        if (Objects.isNull(rmap.get(key))) {
            return null;
        }
        return rmap.get(key);
    }

    public String getErrorMsg(String errCode) {
        if (StringUtils.isBlank(errCode)) {
            return null;
        }
        String msg = null;
        switch (errCode) {
            case "INVALID_REQUEST":
                msg = "参数错误";
                break;
            case "NOAUTH":
                msg = "商户无此接口权限";
                break;
            case "NOTENOUGH":
                msg = "余额不足";
                break;
            case "ORDERPAID":
                msg = "商户订单已支付";
                break;
            case "ORDERCLOSED":
                msg = "订单已关闭";
                break;
            case "SYSTEMERROR":
                msg = "系统错误";
                break;
            case "APPID_NOT_EXIST":
                msg = "APPID不存在";
                break;
            case "MCHID_NOT_EXIST":
                msg = "MCHID不存在";
                break;
            case "APPID_MCHID_NOT_MATCH":
                msg = "appid和mch_id不匹配";
                break;
            case "LACK_PARAMS":
                msg = "缺少参数";
                break;
            case "OUT_TRADE_NO_USED":
                msg = "商户订单号重复";
                break;
            case "SIGNERROR":
                msg = "签名错误";
                break;
            case "XML_FORMAT_ERROR":
                msg = "XML格式错误";
                break;
            case "REQUIRE_POST_METHOD":
                msg = "请使用post方法";
                break;
            case "POST_DATA_EMPTY":
                msg = "post数据为空";
                break;
            case "NOT_UTF8":
                msg = "编码格式错误";
                break;
            case "ORDERNOTEXIST":
                msg = "此交易订单号不存在";
                break;
            default:
                msg = errCode;
        }
        return msg;
    }


}
